<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>

    let obj = {name: 'jack', age: 21, hobbies: ['study', ['basketball', 'reading']]}

    function observer(data) {
        if (typeof data == null || typeof data !== 'object') {
            return data
        }
        for (let key in data) {
            defineReactive(data, key, data[key])
        }
    }

    function defineReactive(target, key, value) {
        observer(value)

        Object.defineProperty(target, key, {
            get() {
                // 记录对应的值watcher
                return value
            },
            set(newValue) {
                // 让记录的watcher重新显示
                if (value !== newValue) {
                    value = newValue
                    observer(newValue)
                }
            }
        })
    }

    observer(obj)

    obj.msg = "ok"
    // 在Vue2中，也可以使用obj.hobbies[20] = "xxx"  索引的方式，虽然比较少见，但可以使用
    // 这样会导致性能非常差，所以在Vue3中使用了Proxy
    console.log(obj)
</script>
</body>
</html>
